/**
 * Copyright 2019-2022 Huawei Technologies Co., Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "hiai_tensor_aipp_para_local.h"

#include "framework/c/hiai_tensor_aipp_para.h"
#include "securec.h"
#include "hiai_tensor_aipp_para_util.h"
#include "hiai_tensor_aipp_para_def.h"

typedef struct HIAI_TensorAippParaLocal {
    uint32_t inputIndex;
    uint32_t inputAippIndex;
    void* buffer;
    size_t size;
    void* handle;
} HIAI_TensorAippParaLocal;

static const uint8_t MAX_BATCH_NUM = 127;
#define HIAI_EXPECT_NOT_NULL_R(ptr, ret) \
    if ((ptr) == NULL) { \
        return ret; \
    }

void* HIAI_TensorAippPara_CreateLocal(uint32_t batchNum)
{
    if (batchNum > MAX_BATCH_NUM) {
        return NULL;
    }

    size_t size = sizeof(HIAI_MR_TensorAippCommPara) + sizeof(HIAI_MR_TensorAippBatchPara) * batchNum;
    void* data = malloc(size);
    HIAI_EXPECT_NOT_NULL_R(data, NULL);

    (void)memset_s(data, size, 0, size);

    HIAI_TensorAippParaLocal* localPara = (HIAI_TensorAippParaLocal*)malloc(sizeof(HIAI_TensorAippParaLocal));
    if (localPara == NULL) {
        goto FREE_BUFFER;
    }
    (void)memset_s(localPara, sizeof(HIAI_TensorAippParaLocal), 0, sizeof(HIAI_TensorAippParaLocal));

    localPara->buffer = data;
    localPara->size = size;
    return localPara;

FREE_BUFFER:
    free(data);
    return NULL;
}

void* HIAI_TensorAippPara_GetRawBufferLocal(const void* handle)
{
    HIAI_EXPECT_NOT_NULL_R(handle, NULL);
    return ((HIAI_TensorAippParaLocal*)handle)->buffer;
}

int32_t HIAI_TensorAippPara_GetRawBufferSizeLocal(const void* handle)
{
    HIAI_EXPECT_NOT_NULL_R(handle, 0);
    return (int32_t)((HIAI_TensorAippParaLocal*)handle)->size;
}

void* HIAI_TensorAippPara_GetHandleLocal(const void* handle)
{
    (void)handle;
    return NULL;
}

int32_t HIAI_TensorAippPara_GetInputIndexLocal(const void* handle)
{
    HIAI_EXPECT_NOT_NULL_R(handle, -1);
    return (int32_t)((HIAI_TensorAippParaLocal*)handle)->inputIndex;
}

void HIAI_TensorAippPara_SetInputIndexLocal(void* handle, uint32_t inputIndex)
{
    if (handle == NULL) {
        return;
    }
    ((HIAI_TensorAippParaLocal*)handle)->inputIndex = inputIndex;
}

int32_t HIAI_TensorAippPara_GetInputAippIndexLocal(const void* handle)
{
    HIAI_EXPECT_NOT_NULL_R(handle, -1);
    return (int32_t)((HIAI_TensorAippParaLocal*)handle)->inputAippIndex;
}

void HIAI_TensorAippPara_SetInputAippIndexLocal(void* handle, uint32_t inputAippIndex)
{
    if (handle == NULL) {
        return;
    }
    ((HIAI_TensorAippParaLocal*)handle)->inputAippIndex = inputAippIndex;
}

HIAI_Status HIAI_TensorAippPara_GetCscSwitchLocal(void* handle, bool* cscSwitch)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    if (para == NULL || cscSwitch == NULL) {
        return HIAI_FAILURE;
    }

    *cscSwitch = HIAI_TensorAippUtil_GetCscSwitch(para->buffer);
    return HIAI_SUCCESS;
}

HIAI_Status HIAI_TensorAippPara_GetCropSwitchLocal(void* handle, uint32_t batchIndex, bool* cropSwitch)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    if (para == NULL || cropSwitch == NULL) {
        return HIAI_FAILURE;
    }

    *cropSwitch = HIAI_TensorAippUtil_GetCropSwitch(para->buffer, batchIndex);
    return HIAI_SUCCESS;
}

HIAI_Status HIAI_TensorAippPara_GetResizeSwitchLocal(void* handle, uint32_t batchIndex, bool* resizeSwitch)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    if (para == NULL || resizeSwitch == NULL) {
        return HIAI_FAILURE;
    }

    *resizeSwitch = HIAI_TensorAippUtil_GetResizeSwitch(para->buffer, batchIndex);
    return HIAI_SUCCESS;
}

HIAI_Status HIAI_TensorAippPara_GetPadSwitchLocal(void* handle, uint32_t batchIndex, bool* padSwitch)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    if (para == NULL || padSwitch == NULL) {
        return HIAI_FAILURE;
    }

    *padSwitch = HIAI_TensorAippUtil_GetPadSwitch(para->buffer, batchIndex);
    return HIAI_SUCCESS;
}

HIAI_Status HIAI_TensorAippPara_GetBatchCountLocal(void* handle, uint32_t* batchCount)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    if (para == NULL || batchCount == NULL) {
        return HIAI_FAILURE;
    }

    *batchCount = HIAI_TensorAippUtil_GetBatchCount(para->buffer);
    return HIAI_SUCCESS;
}

HIAI_Status HIAI_TensorAippPara_SetInputFormatLocal(void* handle, HIAI_ImageFormat inputFormat)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetInputFormat(para->buffer, inputFormat);
}

HIAI_Status HIAI_TensorAippPara_GetInputFormatLocal(void* handle, HIAI_ImageFormat* inputFormat)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    *inputFormat = HIAI_TensorAippUtil_GetInputFormat(para->buffer);
    return HIAI_SUCCESS;
}

HIAI_Status HIAI_TensorAippPara_SetInputShapeLocal(void* handle, uint32_t srcImageW, uint32_t srcImageH)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetInputShape(para->buffer, srcImageW, srcImageH);
}

HIAI_Status HIAI_TensorAippPara_GetInputShapeLocal(void* handle, uint32_t* srcImageW, uint32_t* srcImageH)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetInputShape(para->buffer, srcImageW, srcImageH);
}

HIAI_Status HIAI_TensorAippPara_SetCscParaLocal(void* handle, HIAI_ImageFormat inputFormat,
    HIAI_ImageFormat targetFormat, HIAI_ImageColorSpace colorSpace) // 转换
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetCscPara(para->buffer, inputFormat, targetFormat, colorSpace);
}

HIAI_Status HIAI_TensorAippPara_GetCscParaLocal(void* handle, HIAI_ImageFormat* inputFormat,
    HIAI_ImageFormat* targetFormat, HIAI_ImageColorSpace* colorSpace)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetCscPara(para->buffer, inputFormat, targetFormat, colorSpace);
}

HIAI_Status HIAI_TensorAippPara_SetChannelSwapParaLocal(void* handle, bool rbuvSwapSwitch, bool axSwapSwitch)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetChannelSwapPara(para->buffer, rbuvSwapSwitch, axSwapSwitch);
}

HIAI_Status HIAI_TensorAippPara_GetChannelSwapParaLocal(void* handle, bool* rbuvSwapSwitch, bool* axSwapSwitch)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetChannelSwapPara(para->buffer, rbuvSwapSwitch, axSwapSwitch);
}

HIAI_Status HIAI_TensorAippPara_SetSingleBatchMultiCropLocal(void* handle, bool singleBatchMutiCrop)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);
    return HIAI_TensorAippUtil_SetSingleBatchMultiCrop(para->buffer, singleBatchMutiCrop);
}

bool HIAI_TensorAippPara_GetSingleBatchMultiCropLocal(void* handle)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    if (para == NULL) {
        return false;
    }
    return HIAI_TensorAippUtil_GetSingleBatchMultiCrop(para->buffer);
}

void HIAI_TensorAippPara_DestroyLocal(void* handle)
{
    if (handle == NULL) {
        return;
    }
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    if (para->buffer != NULL) {
        free(para->buffer);
    }
    free(handle);
}

HIAI_Status HIAI_TensorAippPara_SetCropPosLocal(
    void* handle, uint32_t batchIndex, uint32_t cropStartPosW, uint32_t cropStartPosH)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

     /* 对于HIAI_TensorAippParaLocal，直接填充结构体 */
    return HIAI_TensorAippUtil_SetCropPos(para->buffer, batchIndex, cropStartPosW, cropStartPosH);
}

HIAI_Status HIAI_TensorAippPara_SetCropSizeLocal(void* handle,
    uint32_t batchIndex, uint32_t cropSizeW, uint32_t cropSizeH)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetCropSize(para->buffer, batchIndex, cropSizeW, cropSizeH);
}

HIAI_Status HIAI_TensorAippPara_GetCropPosLocal(void* handle,
    uint32_t batchIndex, uint32_t* cropStartPosW, uint32_t* cropStartPosH)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetCropPos(para->buffer, batchIndex, cropStartPosW, cropStartPosH);
}

HIAI_Status HIAI_TensorAippPara_GetCropSizeLocal(void* handle,
    uint32_t batchIndex, uint32_t* cropSizeW, uint32_t* cropSizeH)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetCropSize(para->buffer, batchIndex, cropSizeW, cropSizeH);
}

HIAI_Status HIAI_TensorAippPara_SetResizeParaLocal(void* handle,
    uint32_t batchIndex, uint32_t resizeOutputSizeW, uint32_t resizeOutputSizeH)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetResizePara(para->buffer, batchIndex, resizeOutputSizeW, resizeOutputSizeH);
}

HIAI_Status HIAI_TensorAippPara_GetResizeParaLocal(void* handle,
    uint32_t batchIndex, uint32_t* resizeOutputSizeW, uint32_t* resizeOutputSizeH)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetResizePara(para->buffer, batchIndex, resizeOutputSizeW, resizeOutputSizeH);
}

HIAI_Status HIAI_TensorAippPara_SetPadTopSizeLocal(void* handle, uint32_t batchIndex, uint32_t paddingSizeTop)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetPadTopSize(para->buffer, batchIndex, paddingSizeTop);
}

HIAI_Status HIAI_TensorAippPara_SetPadBottomSizeLocal(void* handle, uint32_t batchIndex, uint32_t paddingSizeBottom)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetPadBottomSize(para->buffer, batchIndex, paddingSizeBottom);
}

HIAI_Status HIAI_TensorAippPara_SetPadLeftSizeLocal(void* handle, uint32_t batchIndex, uint32_t paddingSizeLeft)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetPadLeftSize(para->buffer, batchIndex, paddingSizeLeft);
}

HIAI_Status HIAI_TensorAippPara_SetPadRightSizeLocal(void* handle, uint32_t batchIndex, uint32_t paddingSizeRight)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetPadRightSize(para->buffer, batchIndex, paddingSizeRight);
}

HIAI_Status HIAI_TensorAippPara_SetPadChannelValueLocal(void* handle, uint32_t batchIndex,
    uint32_t chnValue[], uint32_t chnNum)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetPadChannelValue(para->buffer, batchIndex, chnValue, chnNum);
}

HIAI_Status HIAI_TensorAippPara_GetPadTopSizeLocal(void* handle, uint32_t batchIndex, uint32_t* paddingSizeTop)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetPadTopSize(para->buffer, batchIndex, paddingSizeTop);
}

HIAI_Status HIAI_TensorAippPara_GetPadBottomSizeLocal(void* handle, uint32_t batchIndex, uint32_t* paddingSizeBottom)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetPadBottomSize(para->buffer, batchIndex, paddingSizeBottom);
}

HIAI_Status HIAI_TensorAippPara_GetPadLeftSizeLocal(void* handle, uint32_t batchIndex, uint32_t* paddingSizeLeft)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetPadLeftSize(para->buffer, batchIndex, paddingSizeLeft);
}

HIAI_Status HIAI_TensorAippPara_GetPadRightSizeLocal(void* handle, uint32_t batchIndex, uint32_t* paddingSizeRight)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetPadRightSize(para->buffer, batchIndex, paddingSizeRight);
}

HIAI_Status HIAI_TensorAippPara_GetPadChannelValueLocal(void* handle, uint32_t batchIndex,
    uint32_t chnValue[], uint32_t chnNum)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetPadChannelValue(para->buffer, batchIndex, chnValue, chnNum);
}

HIAI_Status HIAI_TensorAippPara_SetDtcPixelMeanParaLocal(void* handle, uint32_t batchIndex,
    int32_t pixelMeanPara[], uint32_t chnNum)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetDtcPixelMeanPara(para->buffer, batchIndex, pixelMeanPara, chnNum);
}

HIAI_Status HIAI_TensorAippPara_SetDtcPixelMinParaLocal(void* handle, uint32_t batchIndex,
    float pixelMinPara[], uint32_t chnNum)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetDtcPixelMinPara(para->buffer, batchIndex, pixelMinPara, chnNum);
}

HIAI_Status HIAI_TensorAippPara_SetDtcPixelVarReciParaLocal(void* handle, uint32_t batchIndex,
    float pixelVarReciPara[], uint32_t chnNum)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetDtcPixelVarReciPara(para->buffer, batchIndex, pixelVarReciPara, chnNum);
}

HIAI_Status HIAI_TensorAippPara_GetDtcPixelMeanParaLocal(void* handle, uint32_t batchIndex,
    int32_t pixelMeanPara[], uint32_t chnNum)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetDtcPixelMeanPara(para->buffer, batchIndex, pixelMeanPara, chnNum);
}

HIAI_Status HIAI_TensorAippPara_GetDtcPixelMinParaLocal(void* handle, uint32_t batchIndex,
    float pixelMinPara[], uint32_t chnNum)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetDtcPixelMinPara(para->buffer, batchIndex, pixelMinPara, chnNum);
}

HIAI_Status HIAI_TensorAippPara_GetDtcPixelVarReciParaLocal(void* handle, uint32_t batchIndex,
    float pixelVarReciPara[], uint32_t chnNum)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetDtcPixelVarReciPara(para->buffer, batchIndex, pixelVarReciPara, chnNum);
}

HIAI_Status HIAI_TensorAippPara_SetRotateAngleLocal(void* handle, uint32_t batchIndex, float rotateAngle)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_SetRotateAngle(para->buffer, batchIndex, rotateAngle);
}

HIAI_Status HIAI_TensorAippPara_GetRotateAngleLocal(void* handle, uint32_t batchIndex, float* rotateAngle)
{
    HIAI_TensorAippParaLocal* para = (HIAI_TensorAippParaLocal*)handle;
    HIAI_EXPECT_NOT_NULL_R(para, HIAI_FAILURE);

    return HIAI_TensorAippUtil_GetRotateAngle(para->buffer, batchIndex, rotateAngle);
}